package com.demomaster.quickcompat.util

import java.nio.ByteBuffer
import kotlin.math.min

class ByteUtil {
    companion object {

        /**
         * short[] 转 byte[]
         */
        @JvmStatic
        fun toBytes(src: ShortArray): ByteArray {
            val count = src.size
            val dest = ByteArray(count shl 1)
            for (i in 0 until count) {
                dest[i * 2] = src[i].toByte()
                dest[i * 2 + 1] = (src[i].toInt() shr 8).toByte()
            }
            return dest
        }


        /**
         * short[] 转 byte[]
         */
        @JvmStatic
        fun toBytes(src: Short): ByteArray {
            val dest = ByteArray(2)
            dest[0] = src.toByte()
            dest[1] = (src.toInt() shr 8).toByte()
            return dest
        }

        /**
         * String 转 byte[]
         */
        @JvmStatic
        fun stringToBytes(str: String): ByteArray {
            return str.toByteArray()
        }

        /**
         * long类型转成byte数组
         */
        @JvmStatic
        fun toBytes(number: Long): ByteArray {
            val buffer = ByteBuffer.allocate(8)
            buffer.putLong(0, number)
            return buffer.array()
        }
        /**
         * 字节数组转int 支持数组位数1-4
         * @param src
         * @param offset
         * @return
         */
        @JvmStatic
        fun toInt(srcBytes: ByteArray?, offset: Int = 0): Int {
            return toInt(srcBytes, offset, true)
        }

        @JvmStatic
        fun toInt(
            srcBytes: ByteArray?,
            offset: Int = 0,
            isBigEndian: Boolean = true // 新增参数：是否使用大端序
        ): Int {
            requireNotNull(srcBytes) { "Source array cannot be null" }
            require(offset >= 0 && offset < srcBytes.size) { "Offset out of bounds" }

            var result = 0
            val count = minOf(4, srcBytes.size - offset) // 最多处理 4 个字节

            for (i in 0 until count) {
                val byteIndex = if (isBigEndian) offset + i else offset + count - 1 - i
                result = result shl 8 // 左移 8 位为下一个字节腾出空间
                result = result or (srcBytes[byteIndex].toInt() and 0xFF) // 添加当前字节
            }

            return result
        }

        /**
         * 处理有符号类型的数据
         */
        @JvmStatic
        fun toInt2(src: ByteArray?, offset: Int=0): Int {
            require(!(src == null || offset < 0 || offset + 4 > src.size)) { "Invalid parameters" }
            // 检查最高有效字节的符号位
            val isNegative = (src[offset].toInt() and 0x80) != 0
            var result = 0
            for (i in 0..3) {
                // 将 byte 转换为 int 并进行无符号处理
                result = (result shl 8) or (src[offset + i].toInt() and 0xFF)
            }
            // 如果是负数，进行符号扩展
            if (isNegative) {
                // 对于负数，Java 的 int 类型会自动处理符号扩展，所以我们只需要返回结果
                // 如果你想要更明确地处理，可以使用下面这行代码：
                result = (result.toLong() or (-0x100000000L ushr (32 - 8 * 4))).toInt()
            }
            return result
        }
        @JvmStatic
        fun toString(b: ByteArray): String {
            return b.contentToString()
        }
        @JvmStatic
        fun bytesToHexString(bytes: ByteArray, withSpaces: Boolean = true): String {
            val sb = StringBuilder()
            for (i in bytes.indices) {
                sb.append(String.format("%02X", bytes[i].toInt() and 0xFF))
                if (withSpaces && i < bytes.lastIndex) {
                    sb.append(" ")
                }
            }
            return sb.toString()
        }

        @JvmStatic
        fun hexStringToBytes(hexString: String): ByteArray {
            // 移除空格和换行符
            val cleanedHexString = hexString.replace("\\s|\\r|\\n".toRegex(), "")

            // 确保输入字符串长度是偶数，并且只包含有效的十六进制字符
            require(cleanedHexString.length % 2 == 0) { "Hex string must have an even length after cleaning" }
            require(cleanedHexString.all { it in '0'..'9' || it in 'a'..'f' || it in 'A'..'F' }) { "Invalid hex string" }

            val len = cleanedHexString.length
            val data = ByteArray(len / 2)

            for (i in 0 until len step 2) {
                val highNibble = Character.digit(cleanedHexString[i], 16)
                val lowNibble = Character.digit(cleanedHexString[i + 1], 16)
                var byteValue = (highNibble shl 4) + lowNibble
                data[i / 2] = byteValue.toByte()
            }

            return data
        }

        /**
         * 由于 Kotlin 的 Byte 类型是有符号的，因此直接将大于 127 的值转换为 Byte 会导致负数。为了避免这种情况，我们可以使用 Int 来存储每个字节的值（0 到 255），并在需要时解释这些值为有符号或无符号。
         */
        @JvmStatic
        fun hexStringToIntArray(hexString: String): IntArray {
            // 移除空格和换行符
            val cleanedHexString = hexString.replace("\\s|\\r|\\n".toRegex(), "")

            // 确保输入字符串长度是偶数，并且只包含有效的十六进制字符
            require(cleanedHexString.length % 2 == 0) { "Hex string must have an even length after cleaning" }
            require(cleanedHexString.all { it in '0'..'9' || it in 'a'..'f' || it in 'A'..'F' }) { "Invalid hex string" }

            val len = cleanedHexString.length
            val data = IntArray(len / 2)

            for (i in 0 until len step 2) {
                val highNibble = Character.digit(cleanedHexString[i], 16)
                val lowNibble = Character.digit(cleanedHexString[i + 1], 16)
                data[i / 2] = (highNibble shl 4) + lowNibble
            }

            return data
        }

        /**
         * 将 int 转换为指定字节数的16进制字符串，确保每个字节都是两位。
         * @param value 需要转换的整数值
         * @param byteCount 期望的字节数（每个字节用两位表示）
         * @return 动态长度的十六进制字符串
         */
        @JvmStatic
        fun intToHexString(value: Int, byteCount: Int): String {
            var value = value
            require(!(byteCount <= 0 || byteCount > 4)) {  // 整型最多4个字节
                "Byte count must be between 1 and 4"
            }
            // 确保只取最低的所需位数
            value = value and (1 shl (byteCount * 8)) - 1
            // 使用格式化字符串来保证每个字节都有两位
            val formatBuilder = java.lang.StringBuilder("%0")
            formatBuilder.append(byteCount * 2).append("X") // 每个字节两位，总共 byteCount * 2 位
            return String.format(formatBuilder.toString(), value)
        }

        /**
         * 将 int 转换为指定字节数的数组，只保留最低的有效位。
         *
         * @param value     需要转换的整数值
         * @param byteCount 期望的字节数（每个字节8位）
         * @return 包含指定字节数的数组
         * @throws IllegalArgumentException 如果 byteCount 不在有效范围内 (1到4)
         */
        @JvmStatic
        fun intToBytes(value: Int, byteCount: Int=4,offset: Int=0): ByteArray {
            require(byteCount in 1..4) { "Byte count must be between 1 and 4" }

            // 确保只取最低的所需位数
            val mask = when (byteCount) {
                1 -> 0xFF
                2 -> 0xFFFF
                3 -> 0xFFFFFF
                else -> 0xFFFFFFFF // 4 bytes
            }
            var maskedValue = value and mask.toInt()
            val bytes = ByteArray(byteCount)
            for (i in 0 until byteCount) {
                bytes[i] = ((maskedValue ushr (8 * (byteCount - i - 1))) and 0xFF).toByte()
            }
            return bytes
        }

        /**
         * 合并两个字节数组为一个新的字节数组。
         *
         * @param array1 第一个字节数组
         * @param array2 第二个字节数组
         * @return 合并后的字节数组
         */
        @JvmStatic
        fun mergeByteArrays(array1: ByteArray, array2: ByteArray): ByteArray {
            // 创建一个新的数组，长度为两个数组之和
            val result = ByteArray(array1.size + array2.size)
            // 将第一个数组复制到结果数组中
            System.arraycopy(array1, 0, result, 0, array1.size)
            // 将第二个数组复制到结果数组中，从array1.length开始
            System.arraycopy(array2, 0, result, array1.size, array2.size)
            return result
        }

        /**
         * 字节数组到long的转换.
         */
        @JvmStatic
        fun toLong(b: ByteArray): Long {
            val buffer = ByteBuffer.allocate(8)
            buffer.put(b, 0, b.size)
            return buffer.getLong()
        }

        /**
         * byte[] 转 short[]
         * short： 2字节
         */
        @JvmStatic
        fun toShorts(src: ByteArray): ShortArray {
            val count = src.size shr 1
            val dest = ShortArray(count)
            for (i in 0 until count) {
                dest[i] =
                    ((src[i * 2].toInt() and 0xff) or ((src[2 * i + 1].toInt() and 0xff) shl 8)).toShort()
            }
            return dest
        }

    }
}